﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.ComponentModel;
using System.Data;
using System.Globalization;
using System.Data.Common;
using ResourceBlender.DAL;
using ResourceBlender.Core;

namespace ResourceBlender.Express {
    /// <summary>
    /// A window to show unused resources.
    /// </summary>
    public partial class WinUnusedResources : Window {
        public WinUnusedResources() :
            this(new ObservableSortedDictionary<string, CultureInfo>(new Comparers.CultureInfoEnglshNameComparer(), new Comparers.StringEqualityComparer())) { }

        /// <summary>
        /// Initializes a new <see cref="WinUnusedResources"/> to display the specified languages.
        /// </summary>
        /// <param name="languages">The languages to show as RadioButtons for which unused resources can be shown.</param>
        public WinUnusedResources(ObservableSortedDictionary<string, CultureInfo> languages) {
            InitializeComponent();
            BackgroundWorker worker = new BackgroundWorker();
            worker.DoWork += (s, dwe) => {
                if(languages.Count == 0) {
                    //ObservableDictionary<string, CultureInfo> uniqueLangs = ResourceBlenderDAL.GetUniqueLanguages();
                    var uniqueLangs = ResourceBlenderDAL.GetUniqueLanguages();
                    foreach(KeyValuePair<string, CultureInfo> lang in uniqueLangs) {
                        languages.Add(lang.Key, lang.Value);
                    }
                }
            };
            worker.RunWorkerCompleted += (s, rwe) => {
                SetStatus(null, false);
                lstUnusedResources.IsEnabled = true;
                lstLanguages.ItemsSource = languages;
                if(rwe.Error != null) {
                    DialogBox.Show(this, rwe.Error.Message, "Error", DialogBox.DialogBoxType.OK, DialogBox.DialogBoxIcon.Error);
                } else {
                    if(languages.Count > 0) {
                        lstLanguages.SelectedIndex = 0;
                        NavigationCommands.Refresh.Execute(null, null);
                    } else {
                        DialogBox.ShowAlert(this, "No resources have been added", "Error");
                        Close();
                    }
                }

            };
            SetStatus("Loading available languages...", true);
            lstUnusedResources.IsEnabled = false;
            worker.RunWorkerAsync();
        }

        /// <summary>
        /// Determines whether the RefreshResources command can be executed
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.Input.CanExecuteRoutedEventArgs"/> instance containing the event data.</param>
        private void CanExecuteRefreshResources(object sender, CanExecuteRoutedEventArgs e) {
            e.CanExecute = this.IsLoaded && lstLanguages.SelectedValue != null;
        }

        /// <summary>
        /// Shows unused resources for the selected language.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void RefreshResources(object sender, RoutedEventArgs e) {
            if(lstLanguages.SelectedValue == null) {
                return;
            }
            string language = lstLanguages.SelectedValue.ToString();
            BackgroundWorker worker = new BackgroundWorker();
            worker.DoWork += (s, dwe) => {
                DataTable dtAvailability = ResourceBlenderDAL.GetUnusedResources(language);
                dwe.Result = dtAvailability;
            };
            worker.RunWorkerCompleted += (s, rwe) => {
                SetStatus(null, false);
                lstUnusedResources.IsEnabled = true;
                if(rwe.Error != null) {
                    DialogBox.Show(this, rwe.Error.Message, "Error", DialogBox.DialogBoxType.OK, DialogBox.DialogBoxIcon.Error);
                } else {
                    DataTable dt = rwe.Result as DataTable;
                    if(dt != null) {
                        int numUnused = dt.DefaultView.Count;
                        SetStatus(string.Format("{0} unused {1} for {2}", numUnused, numUnused == 1 ? "resource" : "resources", ((KeyValuePair<string, CultureInfo>)lstLanguages.SelectedItem).Value.EnglishName), false);
                        lstUnusedResources.DataContext = dt;
                    }
                }
            };
            SetStatus("Loading unused resources...", true);
            lstUnusedResources.IsEnabled = false;
            worker.RunWorkerAsync();
        }

        /// <summary>
        /// Determines whether ththe DeleteResources command can be executed
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.Input.CanExecuteRoutedEventArgs"/> instance containing the event data.</param>
        private void CanExecuteDeleteResources(object sender, CanExecuteRoutedEventArgs e) {
            e.CanExecute = this.IsLoaded && lstUnusedResources.SelectedItems.Count > 0;
        }

        /// <summary>
        /// Prompts to delete resources from the database.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void PromptDeleteResources(object sender, RoutedEventArgs e) {
            if(lstLanguages.SelectedValue == null) {
                return;
            }
            List<string> selectedResources = new List<string>();
            foreach(DataRowView row in lstUnusedResources.SelectedItems) {
                selectedResources.Add(row[0].ToString());
            }
            BackgroundWorker worker = new BackgroundWorker();
            worker.DoWork += (s, dwe) => {
                dwe.Result = ResourceBlenderDAL.GetResourceAvailability(selectedResources.Select(id => int.Parse(id)).ToArray());
            };
            worker.RunWorkerCompleted += (s, rwe) => {
                SetStatus(null, false);
                btnDelete.IsEnabled = true;
                lstUnusedResources.IsEnabled = true;
                if(rwe.Error != null) {
                    DialogBox.ShowAlert(this, "Error deleting resources: "+rwe.Error.Message, "Error");
                } else {
                    if(DialogBox.Show(this, string.Format("Are you sure you want to delete {0} resources.\n\nAcross all languages, {1} translations will be deleted.", selectedResources.Count, rwe.Result), "Confirm Delete", DialogBox.DialogBoxType.YesNo, DialogBox.DialogBoxIcon.Question, DialogBox.DialogBoxButton.No) == DialogBox.DialogBoxButton.Yes) {
                        DeleteResources(selectedResources);
                    }
                }
            };
            SetStatus("Loading...", true);
            lstUnusedResources.IsEnabled = false;
            btnDelete.IsEnabled = false;
            worker.RunWorkerAsync();
        }

        /// <summary>
        /// Deletes resources from the database.
        /// </summary>
        /// <param name="resourceIds">The resource ids.</param>
        private void DeleteResources(List<string> resourceIds) {
            BackgroundWorker worker = new BackgroundWorker();
            worker.DoWork += (s, dwe) => {
                ResourceBlenderDAL.DeleteResources(resourceIds.Select(id => int.Parse(id)));
            };
            worker.RunWorkerCompleted += (s, rwe) => {
                SetStatus(null, false);
                btnDelete.IsEnabled = true;
                lstUnusedResources.IsEnabled = true;
                try {
                    int numUnused = (lstUnusedResources.DataContext as DataTable).DefaultView.Count;
                    SetStatus(string.Format("{0} unused {1} for {2}", numUnused, numUnused == 1 ? "resource" : "resources", ((KeyValuePair<string, CultureInfo>)lstLanguages.SelectedItem).Value.EnglishName), false);
                } catch { }
                NavigationCommands.Refresh.Execute(null, null);
            };
            SetStatus("Loading...", true);
            btnDelete.IsEnabled = false;
            lstUnusedResources.IsEnabled = false;
            worker.RunWorkerAsync(resourceIds);
        }

        /// <summary>
        /// Determines whether all resources can be selected.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.Input.CanExecuteRoutedEventArgs"/> instance containing the event data.</param>
        private void CanExecuteSelectAll(object sender, CanExecuteRoutedEventArgs e) {
            e.CanExecute = this.IsLoaded && lstUnusedResources.HasItems;
        }

        /// <summary>
        /// Selects all resources.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.Input.ExecutedRoutedEventArgs"/> instance containing the event data.</param>
        private void SelectAllResources(object sender, ExecutedRoutedEventArgs e) {
            lstUnusedResources.SelectAll();
        }

        /// <summary>
        /// Shows the help file.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.Input.ExecutedRoutedEventArgs"/> instance containing the event data.</param>
        private void ShowHelp(object sender, ExecutedRoutedEventArgs e) {
            WPFUtils.OpenHelp("Unused.Resources.html");
        }

        /// <summary>
        /// Sets the text on the status message.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="showProgress"><c>true</c> if the progress bar should be shown, otherwise <c>false</c>.</param>
        private void SetStatus(string message, bool showProgress) {
            prgStatus.Visibility = showProgress ? Visibility.Visible : Visibility.Hidden;
            if(message == null) {
                lblStatus.Visibility = Visibility.Hidden;
            } else {
                lblStatus.Visibility = Visibility.Visible;
                lblStatus.Content = message;
            }
        }
    }
}
